package com.zhku.orders.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.StringUtils;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhku.base.exception.TaoTaoException;
import com.zhku.base.model.PageParams;
import com.zhku.base.model.PageResult;
import com.zhku.base.model.RestResponse;
import com.zhku.orders.config.AlipayConfig;
import com.zhku.orders.feignclient.GoodsClient;
import com.zhku.orders.feignclient.TtGoods;
import com.zhku.orders.feignclient.TtUserAddress;
import com.zhku.orders.feignclient.UserClient;
import com.zhku.orders.mapper.TtOrdersGoodsMapper;
import com.zhku.orders.mapper.TtOrdersLogisticsMapper;
import com.zhku.orders.mapper.TtOrdersMapper;
import com.zhku.orders.mapper.TtPayRecordMapper;
import com.zhku.orders.model.dto.*;
import com.zhku.orders.model.po.*;
import com.zhku.orders.service.OrderService;
import com.zhku.base.utils.IdWorkerUtils;
import com.zhku.base.utils.QRCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    TtOrdersMapper ordersMapper;

    @Autowired
    TtOrdersGoodsMapper ordersGoodsMapper;

    @Autowired
    TtPayRecordMapper payRecordMapper;

    @Autowired
    TtOrdersLogisticsMapper ttOrdersLogisticsMapper;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    OrderServiceImpl currentProxy;

    @Value("${pay.qrcodeurl}")
    String qrcodeurl;

    @Value("${pay.alipay.APP_ID}")
    String APP_ID;
    @Value("${pay.alipay.APP_PRIVATE_KEY}")
    String APP_PRIVATE_KEY;

    @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}")
    String ALIPAY_PUBLIC_KEY;

    @Autowired
    UserClient userClient;

    @Autowired
    GoodsClient goodsClient;

    @Transactional
    @Override
    public PayRecordDto createOrder(String userId, AddOrderDto addOrderDto) {

        //插入订单表,订单主表，订单明细表
        TtOrders xcOrders = saveXcOrders(userId, addOrderDto);
        //根据订单号，查看用户买了多少商品
        Long ordersId = xcOrders.getId();
        LambdaQueryWrapper<TtOrdersGoods> queryWrapper = new LambdaQueryWrapper<>();
        List<TtOrdersGoods> ttOrdersGoods = ordersGoodsMapper.selectList(queryWrapper);
        for (TtOrdersGoods ttOrdersGood : ttOrdersGoods) {
            //插入物流表
            TtOrdersLogistics ttOrdersLogistics = new TtOrdersLogistics();
            String id = UUID.randomUUID().toString();
            ttOrdersLogistics.setId(id);
            ttOrdersLogistics.setUserFlag("0");
            ttOrdersLogistics.setUserStatus("0");
            ttOrdersLogistics.setShopFlag("0");
            ttOrdersLogistics.setShopStatus("0");
            ttOrdersLogistics.setGoodsId(ttOrdersGood.getGoodsId());
            ttOrdersLogistics.setUserId(xcOrders.getUserId());
            ttOrdersLogistics.setStatus("0");
            ttOrdersLogistics.setShopId(ttOrdersGood.getShopId());
            ttOrdersLogistics.setUserAddressId(addOrderDto.getUserAddressId());
            RestResponse<TtUserAddress> address = userClient.getAddress(addOrderDto.getUserAddressId());
            TtUserAddress ttUserAddress = address.getResult();
            String province = ttUserAddress.getProvince();
            String city = ttUserAddress.getCity();
            String county = ttUserAddress.getCounty();
            String addressDetail = ttUserAddress.getAddressDetail();
            ttOrdersLogistics.setEndaddresss(province+city+county+addressDetail);
            ttOrdersLogistics.setStartaddress("");
            ttOrdersLogistics.setNowaddress("当前位置：...");
            int insert = ttOrdersLogisticsMapper.insert(ttOrdersLogistics);
            if (insert <= 0) {
                throw new TaoTaoException("创建物流表失败");
            }
        }


        //插入支付记录
        TtPayRecord payRecord = createPayRecord(xcOrders);
        Long payNo = payRecord.getPayNo();

        //生成二维码
        QRCodeUtil qrCodeUtil = new QRCodeUtil();
        //支付二维码的url
        String url = String.format(qrcodeurl, payNo);
        //二维码图片
        String qrCode = null;
        try {
            qrCode = qrCodeUtil.createQRCode(url, 200, 200);
        } catch (IOException e) {
            TaoTaoException.cast("生成二维码出错");
        }

        PayRecordDto payRecordDto = new PayRecordDto();
        BeanUtils.copyProperties(payRecord, payRecordDto);
        payRecordDto.setQrcode(qrCode);

        return payRecordDto;
    }

    @Override
    public TtPayRecord getPayRecordByPayno(String payNo) {
        TtPayRecord xcPayRecord = payRecordMapper.selectOne(new LambdaQueryWrapper<TtPayRecord>().eq(TtPayRecord::getPayNo, payNo));
        return xcPayRecord;
    }

    @Override
    public PayRecordDto queryPayResult(String payNo) {

        //调用支付宝的接口查询支付结果
        PayStatusDto payStatusDto = queryPayResultFromAlipay(payNo);

        //拿到支付结果更新支付记录表和订单表的支付状态
        currentProxy.saveAliPayStatus(payStatusDto);
        //要返回最新的支付记录信息
        TtPayRecord payRecordByPayno = getPayRecordByPayno(payNo);
        PayRecordDto payRecordDto = new PayRecordDto();
        BeanUtils.copyProperties(payRecordByPayno, payRecordDto);

        return payRecordDto;
    }

    /**
     * 请求支付宝查询支付结果
     *
     * @param payNo 支付交易号
     * @return 支付结果
     */
    public PayStatusDto queryPayResultFromAlipay(String payNo) {

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", payNo);
        request.setBizContent(bizContent.toString());
        //支付宝返回的信息
        String body = null;
        try {
            AlipayTradeQueryResponse response = alipayClient.execute(request); //通过alipayClient调用API，获得对应的response类
            if (!response.isSuccess()) {//交易不成功
                TaoTaoException.cast("请求支付宝查询支付结果失败");
            }
            body = response.getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
            TaoTaoException.cast("请求支付查询支付结果异常");
        }
        Map bodyMap = JSON.parseObject(body, Map.class);
        Map alipay_trade_query_response = (Map) bodyMap.get("alipay_trade_query_response");

        //解析支付结果
        String trade_no = (String) alipay_trade_query_response.get("trade_no");
        String trade_status = (String) alipay_trade_query_response.get("trade_status");
        String total_amount = (String) alipay_trade_query_response.get("total_amount");
        PayStatusDto payStatusDto = new PayStatusDto();
        payStatusDto.setOut_trade_no(payNo);
        payStatusDto.setTrade_no(trade_no);//支付宝的交易号
        payStatusDto.setTrade_status(trade_status);//交易状态
        payStatusDto.setApp_id(APP_ID);
        payStatusDto.setTotal_amount(total_amount);//总金额
        return payStatusDto;
    }

    /**
     * @param payStatusDto 支付结果信息 从支付宝查询到的信息
     * @return void
     * @description 保存支付宝支付结果
     */
    @Transactional
    @Override
    public void saveAliPayStatus(PayStatusDto payStatusDto) {
        //支付记录号
        String payNO = payStatusDto.getOut_trade_no();
        TtPayRecord payRecordByPayno = getPayRecordByPayno(payNO);
        if (payRecordByPayno == null) {
            TaoTaoException.cast("找不到相关的支付记录");
        }
        //拿到相关联的订单id
        Long orderId = payRecordByPayno.getOrderId();
        TtOrders xcOrders = ordersMapper.selectById(orderId);
        if (xcOrders == null) {
            TaoTaoException.cast("找不到相关联的订单");
        }
        //支付状态
        String statusFromDb = payRecordByPayno.getStatus();
        //如果数据库支付的状态已经是成功了，不再处理了
        if ("1".equals(statusFromDb)) {
            return;
        }

        //如果支付成功
        String trade_status = payStatusDto.getTrade_status();//从支付宝查询到的支付结果
        if (trade_status.equals("TRADE_SUCCESS")) {//支付宝返回的信息为支付成功
            //更新支付记录表的状态为支付成功
            payRecordByPayno.setStatus("1");
            //支付宝的订单号
            payRecordByPayno.setOutPayNo(payStatusDto.getTrade_no());
            //第三方支付渠道编号
            payRecordByPayno.setOutPayChannel("Alipay");
            //支付成功时间
            payRecordByPayno.setPaySuccessTime(LocalDateTime.now());
            payRecordMapper.updateById(payRecordByPayno);

            //更新订单表的状态为支付成功
            xcOrders.setStatus("1");//订单状态为交易成功
            ordersMapper.updateById(xcOrders);
            //更新物流表状态为支付成功
            Long ordersId = xcOrders.getId();
            //根据订单号找到有哪些支付成功的商品
            LambdaQueryWrapper<TtOrdersGoods> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(TtOrdersGoods::getOrderId,ordersId);
            List<TtOrdersGoods> goodsList = ordersGoodsMapper.selectList(lambdaQueryWrapper);
            for (TtOrdersGoods ttOrdersGoods : goodsList) {
                LambdaQueryWrapper<TtOrdersLogistics> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(TtOrdersLogistics::getGoodsId,ttOrdersGoods.getGoodsId());
                TtOrdersLogistics ttOrdersLogistics = ttOrdersLogisticsMapper.selectOne(queryWrapper);
                ttOrdersLogistics.setStatus("1");
                ttOrdersLogisticsMapper.updateById(ttOrdersLogistics);
            }

            //删除购物车中已支付的商品
            LambdaQueryWrapper<TtOrdersGoods> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TtOrdersGoods::getOrderId,ordersId);
            List<TtOrdersGoods> ttOrdersGoods = ordersGoodsMapper.selectList(wrapper);
            for (TtOrdersGoods ttOrdersGood : ttOrdersGoods) {
                String goodsId = ttOrdersGood.getGoodsId();
                String userId = xcOrders.getUserId();
                boolean b = userClient.deleteSuccessGoods(userId, goodsId);
                if (!b) {
                    log.error("在用户支付成功后，远程调用用户服务--删除支付成功的购物车商品失败了");
                }
            }
        }
    }

    @Override
    public TtOrders getUserOrder(String id) {
        if (StringUtils.isEmpty(id)) {
            throw new TaoTaoException("传入的订单id为空");
        }
        TtOrders ttOrders = ordersMapper.selectById(id);
        if (ttOrders == null) {
            throw new TaoTaoException("当前订单不存在");
        }
        return ttOrders;
    }

    @Override
    public PageResult<TtOrders> queryUserOrderList(PageParams pageParams, QueryUserOrder queryUserOrder) {
        String userId = queryUserOrder.getUserId();
        if (StringUtils.isEmpty(userId)) {
            throw new TaoTaoException("传入的用户id为空");
        }
        LambdaQueryWrapper<TtOrders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TtOrders::getUserId,userId).eq(TtOrders::getStatus,"1");
        //创建page分页参数对象，参数：当前页码数，每页记录数
        Page<TtOrders> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());
        Page<TtOrders> ttOrdersPage = ordersMapper.selectPage(page, queryWrapper);
        List<TtOrders> items = ttOrdersPage.getRecords();
        for (TtOrders item : items) {
            String orderDetail = item.getOrderDetail();
            List<TtOrdersGoods> ttOrdersGoods = JSON.parseArray(orderDetail, TtOrdersGoods.class);
            List<OrdersPriceDetail> list = new ArrayList<>();
            for (TtOrdersGoods ttOrdersGood : ttOrdersGoods) {
                OrdersPriceDetail ordersPriceDetail = new OrdersPriceDetail();
                BeanUtils.copyProperties(ttOrdersGood,ordersPriceDetail);
                RestResponse<TtGoods> response = goodsClient.getGoods(ttOrdersGood.getGoodsId());
                TtGoods ttGoods = response.getResult();
                ordersPriceDetail.setUrl(ttGoods.getUrl());
                list.add(ordersPriceDetail);
            }
            String orderDetailNew = JSON.toJSONString(list);
            item.setOrderDetail(orderDetailNew);
        }
        long counts = ttOrdersPage.getTotal();
        PageResult<TtOrders> ttOrdersPageResult = new PageResult<>(items,
                counts, pageParams.getPageNo(), pageParams.getPageSize());
        return ttOrdersPageResult;
    }

    @Override
    public PageResult<ReturnShopOrdersDto> queryShopOrderList(PageParams pageParams, QueryShopOrder queryShopOrder) {
        String shopId = queryShopOrder.getShopId();
        if (StringUtils.isEmpty(shopId)) {
            throw new TaoTaoException("传入的店铺id为空");
        }
        LambdaQueryWrapper<TtOrdersGoods> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TtOrdersGoods::getShopId,shopId);
        //创建page分页参数对象，参数：当前页码数，每页记录数
        Page<TtOrdersGoods> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());
        Page<TtOrdersGoods> ttOrdersPage = ordersGoodsMapper.selectPage(page, queryWrapper);
        List<TtOrdersGoods> items = ttOrdersPage.getRecords();
        List<ReturnShopOrdersDto> items2 = new ArrayList<>();
        for (TtOrdersGoods item : items) {
            ReturnShopOrdersDto returnShopOrdersDto = new ReturnShopOrdersDto();
            BeanUtils.copyProperties(item,returnShopOrdersDto);
            Long orderId = item.getOrderId();
            TtOrders ttOrders = ordersMapper.selectById(orderId);
            returnShopOrdersDto.setCreateDate(ttOrders.getCreateDate());
            String userId = ttOrders.getUserId();
            returnShopOrdersDto.setUserId(userId);
            returnShopOrdersDto.setGoodsPrice(item.getGoodsPrice()*item.getNumber());
            items2.add(returnShopOrdersDto);
        }
        long counts = ttOrdersPage.getTotal();
        PageResult<ReturnShopOrdersDto> ttOrdersPageResult = new PageResult<>(items2,
                counts, pageParams.getPageNo(), pageParams.getPageSize());
        return ttOrdersPageResult;
    }

    @Override
    public PageResult<ReturnHotGoodsDto> getHotGoodsList() {
        List<HotGoodsDto> list = ordersGoodsMapper.getHotGoodsList();
        List<ReturnHotGoodsDto> items = new ArrayList<>();
        for (HotGoodsDto hotGoodsDto : list) {
            String goodsId = hotGoodsDto.getGoodsId();
            int count = hotGoodsDto.getCount();
            RestResponse<TtGoods> response = goodsClient.getGoods(goodsId);
            TtGoods goods = response.getResult();
            ReturnHotGoodsDto returnHotGoodsDto = new ReturnHotGoodsDto();
            BeanUtils.copyProperties(goods,returnHotGoodsDto);
            returnHotGoodsDto.setNumber(count);
            items.add(returnHotGoodsDto);
        }
        PageResult<ReturnHotGoodsDto> returnHotGoodsDtoPageResult = new PageResult<>(items,
                0, 0, 0);
        return returnHotGoodsDtoPageResult;
    }

    @Transactional
    @Override
    public void deleteTimeOutOrder(String id) {
        if (StringUtils.isEmpty(id)) {
            throw new TaoTaoException("传入的超时订单id为空");
        }
        long orderId = Long.parseLong(id);
        LambdaQueryWrapper<TtOrders> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(TtOrders::getId,orderId).eq(TtOrders::getStatus,"0");
        int i = ordersMapper.deleteById(lambdaQueryWrapper);
        if (i <= 0) {
            throw new TaoTaoException("删除超时订单失败");
        }
        LambdaQueryWrapper<TtOrdersGoods> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TtOrdersGoods::getOrderId,orderId);
        List<TtOrdersGoods> ttOrdersGoods = ordersGoodsMapper.selectList(queryWrapper);
        for (TtOrdersGoods ttOrdersGood : ttOrdersGoods) {
            LambdaQueryWrapper<TtOrdersLogistics> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TtOrdersLogistics::getGoodsId,ttOrdersGood.getGoodsId()).eq(TtOrdersLogistics::getStatus,"0");
            int delete = ttOrdersLogisticsMapper.delete(wrapper);
            if (delete <= 0) {
                throw new TaoTaoException("删除超时物流表失败");
            }
        }
        int delete = ordersGoodsMapper.delete(queryWrapper);
        if (delete <= 0){
            throw new TaoTaoException("删除订单详细表失败");
        }
    }

    @Override
    public Boolean payGoods(String payNo) {
        if (StringUtils.isEmpty(payNo)) {
            throw new TaoTaoException("传入的支付交易号为空");
        }
        LambdaQueryWrapper<TtPayRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TtPayRecord::getPayNo,payNo);
        TtPayRecord ttPayRecord = payRecordMapper.selectOne(queryWrapper);
        if (ttPayRecord == null) {
            throw new TaoTaoException("输入不存在的支付交易号");
        }
        String status = ttPayRecord.getStatus();
        if ("0".equals(status)) {
            return false;
        }
        return true;
    }

    /**
     * 保存支付记录
     *
     * @param orders
     * @return
     */
    public TtPayRecord createPayRecord(TtOrders orders) {
        //订单id
        Long orderId = orders.getId();
        TtOrders xcOrders = ordersMapper.selectById(orderId);
        //如果此订单不存在不能添加支付记录
        if (xcOrders == null) {
            TaoTaoException.cast("订单不存在");
        }
        //订单状态
        String status = xcOrders.getStatus();
        //如果此订单支付结果为成功，不再添加支付记录，避免重复支付
        if ("1".equals(status)) {//支付成功
            TaoTaoException.cast("此订单已支付");
        }
        //添加支付记录
        TtPayRecord xcPayRecord = new TtPayRecord();
        xcPayRecord.setPayNo(IdWorkerUtils.getInstance().nextId());//支付记录号，将来要传给支付宝
        xcPayRecord.setOrderId(orderId);
        xcPayRecord.setOrderName(xcOrders.getOrderName());
        xcPayRecord.setTotalPrice(xcOrders.getTotalPrice());
        xcPayRecord.setCurrency("CNY");
        xcPayRecord.setCreateDate(LocalDateTime.now());
        xcPayRecord.setStatus("0");//未支付
        xcPayRecord.setUserId(xcOrders.getUserId());
        int insert = payRecordMapper.insert(xcPayRecord);
        if (insert <= 0) {
            TaoTaoException.cast("插入支付记录失败");
        }
        return xcPayRecord;
    }

    /**
     * 保存订单信息
     *
     * @param userId
     * @param addOrderDto
     * @return
     */
    public TtOrders saveXcOrders(String userId, AddOrderDto addOrderDto) {
        //插入订单表,订单主表，订单明细表
        //插入订单主表
        TtOrders ttOrders = new TtOrders();
        //使用雪花算法生成订单号
        ttOrders.setId(IdWorkerUtils.getInstance().nextId());
        ttOrders.setTotalPrice(addOrderDto.getTotalPrice());
        ttOrders.setCreateDate(LocalDateTime.now());
        ttOrders.setStatus("0");//未支付
        ttOrders.setUserId(userId);
        ttOrders.setOrderName(addOrderDto.getOrderName());
        List<TtOrdersGoods> orderDetail = addOrderDto.getOrderDetail();
        String orderDetailString = JSON.toJSONString(orderDetail);
        ttOrders.setOrderDetail(orderDetailString);
        int insert = ordersMapper.insert(ttOrders);
        if (insert <= 0) {
            TaoTaoException.cast("添加订单失败");
        }
        //订单id
        Long orderId = ttOrders.getId();
        //插入订单明细表
        //将前端传入的明细json串转成List
        //遍历xcOrdersGoods插入订单明细表
        orderDetail.forEach(goods -> {
            goods.setId(IdWorkerUtils.getInstance().nextId());
            goods.setOrderId(orderId);
            //插入订单明细表
            int insert1 = ordersGoodsMapper.insert(goods);

        });
        return ttOrders;

    }



}
